home *** CD-ROM | disk | FTP | other *** search
/ Hacker's Arsenal - The Cutting Edge of Hacking / Hacker's Arsenal - The Cutting Edge of Hacking.iso / texts / misc / t145.txt < prev    next >
Text File  |  2001-07-11  |  20KB  |  697 lines

  1. == ASM KEYGEN TUTORIAL - WRITTEN BY TERAPHY [PC97]
  2. ===================================================
  3.  
  4. This is the tools i use in this tutorial:
  5.  Soft-Ice 3.01
  6.  W32Dasm 8.9 *Regged*
  7.  Tasm/Tlink
  8.  
  9.  
  10. Getting Started:
  11.  What we should do is to get the registration code,
  12. find where the code is being calculated and rip it out.
  13. I will use two easy programs as examples,
  14. Command Line 97 1.0, and Flywheel V1.02b.
  15.  
  16.  
  17. Command Line 97 1.0: 
  18. (http://www.odyssey.net/subscribers/js01/index.html)
  19.  This program has a real simple code calculation.
  20. I will guide you step by step how to get the serial,
  21. how to rip it and how to make a working keygen.
  22.  
  23. 1. Start the Program
  24.  
  25. 2. Select Register
  26.  
  27. 3. Go into Soft-Ice by pressing Ctrl-D, and set a breakpoint on
  28.    GetDlgItemTextA. Type 'bpx getdlgitemtexta'. Now Press Ctrl-D
  29.    again to get out from Soft-Ice.
  30.  
  31. 4. Enter your name and a serial... I used 'TERAPHY' and '12345'
  32.  
  33. 5. Press OK Button.. Soft-Ice will now show up inside the call
  34.    to GetDlgItemTextA. Press F11 to get out of that call.
  35.  
  36. Scroll up a bit and u will see this
  37.  
  38. :0040254B 6A1E                    push 0000001E
  39. :0040254D 68300B4100              push 00410B30
  40. :00402552 68F0030000              push 000003F0
  41. :00402557 56                      push esi
  42. :00402558 FF1550234100            Call [USER32!GetDlgItemTextA]
  43.  
  44. The memory location being pushed at 40254D is where your name is
  45. stored. Type 'd 410B30', and you should see your name.
  46.  
  47. Below this you'll see
  48.  
  49. :0040255E 6A00                    push 00000000
  50. :00402560 BF300B4100              mov edi, 00410B30
  51. :00402565 6A00                    push 00000000
  52. :00402567 68FC030000              push 000003FC
  53. :0040256C 56                      push esi
  54. :0040256D FF1518234100            Call [USER32!GetDlgItemInt]
  55.  
  56. Step until you reach 40256D. The call to Getdlgitemint returns
  57. what you typed in as serial in eax. Type '? eax' and you will
  58. see this '00003039 0000012345 "09"'. 3039 is 12345 in hex.
  59. Also notice :00402560. This command moves the offset of your name
  60. into edi.
  61.  
  62. Below this, you will see
  63.  
  64. :00402573 B9FFFFFFFF              mov ecx, FFFFFFFF
  65. :00402578 A354A54000              mov dword ptr [0040A554], eax
  66. :0040257D 2BC0                    sub eax, eax
  67. :0040257F F2                      repnz
  68. :00402580 AE                      scasb
  69. :00402581 F7D1                    not ecx
  70. :00402583 49                      dec ecx
  71.  
  72. :00402578 saves your code for later use.
  73. The rest of the code is used to calculate the string length of
  74. your name... After this has been executed ecx contains the length
  75. of your name. In my case '7'.
  76.  
  77. Below this, you'll see
  78.  
  79. :00402584 0FBE05300B4100          movsx eax, byte ptr [00410B30]
  80. :0040258B 0FAFC8                  imul ecx, eax
  81. :0040258E C1E10A                  shl ecx, 0A
  82. :00402591 81C1CCF80200            add ecx, 0002F8CC
  83. :00402597 890D50A54000            mov dword ptr [0040A550], ecx
  84. :0040259D 390D54A54000            cmp dword ptr [0040A554], ecx
  85.  
  86. :00402584 moves the byte of the first letter to eax. 
  87. In my case 54('T'). The next line multiplys eax (54),
  88. with ecx (7). shl ecx, 0A means multiply ecx with 2^10.
  89. And finnaly we add 02F8CC to ecx.
  90. At :0040259D the registration code is compared with what
  91. we typed in, remember it moved our code to [0040A554].
  92. Type '? ecx' and you can see your real code.
  93. But we don't just want the code, do we?
  94. Leave SoftIce and exit Command Line 97.
  95.  
  96. 6. Start W32Dasm, and dissasemble cline97.exe
  97.    Save dissasembly to file and exit.
  98.  
  99. 7. Now we are going to build the keygen itself.
  100. Start your favorite texteditor and enter this code.
  101.  
  102.  
  103. Code Segment Byte Public
  104. Assume   Ds:Code,Cs:Code
  105. Org  100h
  106. P386                ; this enables 386 instructions
  107.                   and 32bit registers
  108.  
  109. Start:
  110.  
  111.     mov  ah,09
  112.     mov  dx,offset Intro
  113.     int  21h        ; Show intro msg
  114.  
  115.     mov  ah,0Ah
  116.     mov  dx,offset Namesto
  117.     int  21h        ; Get name
  118.  
  119.  
  120. Now load the dissasembly (cline97.alf) into your texteditor.
  121. Goto :00402573. Copy all code from here down to :00402591,
  122. and paste it into your asm source.
  123.  
  124. It will look like this
  125. :00402573 B9FFFFFFFF              mov ecx, FFFFFFFF
  126. :00402578 A354A54000              mov dword ptr [0040A554], eax
  127. :0040257D 2BC0                    sub eax, eax
  128. :0040257F F2                      repnz
  129. :00402580 AE                      scasb
  130. :00402581 F7D1                    not ecx
  131. :00402583 49                      dec ecx
  132. :00402584 0FBE05300B4100          movsx eax, byte ptr [00410B30]
  133. :0040258B 0FAFC8                  imul ecx, eax
  134. :0040258E C1E10A                  shl ecx, 0A
  135. :00402591 81C1CCF80200            add ecx, 0002F8CC
  136.  
  137. Now you can start ripping. You should remove everything except the command
  138. itself. The line :00402578 is obviously not needed, because it saves the
  139. inputed regcode for later use, and our keygen does not prompt for regcode,
  140. it calculates =)
  141.  
  142. The source in your program should look like this.
  143.  
  144.     mov ecx, FFFFFFFF
  145.     sub eax, eax
  146.     repnz
  147.     scasb
  148.     not ecx
  149.     dec ecx
  150.     movsx eax, byte ptr [00410B30]
  151.     imul ecx, eax
  152.     shl ecx, 0A
  153.     add ecx, 0002F8CC
  154.  
  155. If you remember, it moved the offset of Name into edi earlier.
  156. So we need to add this before mov ecx, FFFFFFFF
  157.     xor edi,edi
  158.     mov di, offset Namesto+2 ; this must be +2, becaue that's there
  159.                  ; the actuall name begins.
  160.  
  161. The command mov ecx, FFFFFFFF can't be compiled this way, so we
  162. have to change it to mov ecx, 0FFFFFFFFh.
  163.  
  164. movsx eax, byte ptr [00410B30] is not valid either, because
  165. our name is'nt on [00410B30]. This could be changed to
  166.     xor edi,edi
  167.     mov di, offset Namesto+2
  168.     movsx eax, byte ptr [edi]
  169.  
  170. Both 'shl ecx, 0A' and 'add ecx, 0002F8CC' needs to be changed to
  171. valid hex format: 'shl ecx, 0Ah' and 'add ecx 2F8CCh'
  172.  
  173. We now have a source that should look like this
  174.  
  175.     xor edi,edi
  176.     mov di,offset Namesto+2
  177.     mov ecx, 0FFFFFFFFh
  178.     sub eax, eax
  179.     repnz
  180.     scasb
  181.     not ecx
  182.     dec ecx
  183.     xor edi,edi
  184.     mov di,offset Namesto+2    
  185.     movsx eax, byte ptr [edi]
  186.     imul ecx, eax
  187.     shl ecx, 0Ah
  188.     add ecx, 2F8CCh
  189.  
  190. after the dec ecx, we need to add another dec ecx,
  191. because when we enter our name, the last char will not be,
  192. in my case, 'y', it will be 0Dh, the enter key.
  193. This function, as it is, will return, in my case, ecx=8,
  194. not ecx=7 as it should be.
  195.  
  196. movsx eax, byte ptr [edi] moves the ascii code of the first
  197. letter to eax. But, what if the user enters a name with a
  198. small letter? The input box in Command Line 97 automaticly
  199. makes it capital letters. This could be fixed by adding this
  200. code below movsx eax, byte ptr [edi].
  201.  
  202.     cmp eax, 061h        ; compare eax with 61h (a)
  203.     jb capital        ; jump if below
  204.     cmp eax, 07Ah        ; compare eax with 7Ah (z)
  205.     ja capital        ; jump if above
  206.     sub eax,20h        ; convert char to capital
  207. capital:
  208.  
  209. Our code now looks like
  210.  
  211. Code Segment Byte Public
  212. Assume   Ds:Code,Cs:Code
  213. Org  100h
  214. P386                ; this enables 386 instructions
  215.                   and 32bit registers
  216.  
  217. Start:
  218.  
  219.     mov  ah,09
  220.     mov  dx,offset Intro
  221.     int  21h        ; Show intro msg
  222.  
  223.     mov  ah,0Ah
  224.     mov  dx,offset Namesto
  225.     int  21h        ; Get name
  226.  
  227.     xor edi,edi
  228.     mov di,offset Namesto+2
  229.     mov ecx, 0FFFFFFFFh
  230.     sub eax, eax
  231.     repnz
  232.     scasb
  233.     not ecx
  234.     dec ecx
  235.     dec ecx
  236.     xor edi,edi
  237.     mov di,offset Namesto+2    
  238.     movsx eax, byte ptr [edi]
  239.     cmp eax, 061h
  240.     jb capital
  241.     cmp eax, 07Ah
  242.     ja capital
  243.     sub eax,20h
  244. capital:
  245.     imul ecx, eax
  246.     shl ecx, 0Ah
  247.     add ecx, 2F8CCh
  248.  
  249. What we need now is a routine to show the serial.
  250. We know that the serial is the decimal value of ecx.
  251.  
  252.     xor esi,esi
  253.         mov si,offset Serial+9    ; esi is the offset there the
  254.                 ; regnumber will be stored
  255.  
  256.     mov eax,ecx        ; eax should be reg number
  257.         mov ecx,0Ah
  258. KeepGoing:
  259.         xor edx,edx
  260.         div ecx
  261.         add dl,30h
  262.         cmp dl,3Ah
  263.         jl  printnow
  264.         add dl,7
  265. printnow:
  266.         dec esi
  267.         mov [esi],dl
  268.         or eax,eax
  269.         jnz keepgoing
  270.  
  271. After this serial contains the registration code.
  272. You don't really need to understand this code. It can be used
  273. by any keygen there the code is the decimal value of a register.
  274.  
  275. The only thing left to do is to add the command that's writes
  276. this to screen.
  277.  
  278.     mov ah, 9
  279.     mov dx, offset RegPrompt
  280.     int 21h
  281.  
  282. And finnaly quit.
  283.     int 20h
  284.  
  285. The full source should look like this
  286.  
  287. ; COMMAND LINE 97 *KEYGEN*
  288. ; CODED BY TERAPHY [PC97]
  289.  
  290. Code Segment Byte Public
  291. Assume   Ds:Code,Cs:Code
  292. Org  100h
  293. P386                ; this enables 386 instructions
  294.                 ; and 32bit registers
  295.  
  296. Start:
  297.  
  298.     mov  ah,09
  299.     mov  dx,offset Intro
  300.     int  21h        ; Show intro msg
  301.  
  302.     mov  ah,0Ah
  303.     mov  dx,offset Namesto
  304.     int  21h        ; Get name
  305.  
  306.     xor edi,edi
  307.     mov di,offset Namesto+2
  308.     mov ecx, 0FFFFFFFFh
  309.     sub eax, eax
  310.     repnz
  311.     scasb
  312.     not ecx
  313.     dec ecx
  314.     xor edi,edi
  315.     mov di,offset Namesto+2    
  316.     movsx eax, byte ptr [edi]
  317.     cmp eax, 061h
  318.     jb capital
  319.     cmp eax, 07Ah
  320.     ja capital
  321.     sub eax,20h
  322. capital:
  323.     imul ecx, eax
  324.     shl ecx, 0Ah
  325.     add ecx, 2F8CCh
  326.  
  327.     xor esi,esi
  328.         mov si,offset Serial+9
  329.     mov eax,ecx
  330.         mov ecx,0Ah
  331. KeepGoing:
  332.         xor edx,edx
  333.         div ecx
  334.         add dl,30h
  335.         cmp dl,3Ah
  336.         jl  printnow
  337.         add dl,7
  338. printnow:
  339.         dec esi
  340.         mov [esi],dl
  341.         or eax,eax
  342.         jnz keepgoing
  343.  
  344.     mov ah, 9
  345.     mov dx, offset RegPrompt
  346.     int 21h
  347.     
  348.     int 20h
  349.  
  350. Intro        db 13,10,'COMMAND LINE 97 *KEYGEN*'
  351.         db 13,10,'CODED BY TERAPHY [PC97]',13,10
  352.         db 13,10,'Enter your name: $'
  353.  
  354. RegPrompt     db 13,10,'Your registration key is: '
  355. Serial        db 0,0,0,0,0,0,0,0,0,0,13,10,24h
  356.  
  357. Namesto        db 18h,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  358.  
  359. Code Ends
  360. End Start
  361.  
  362. 8. Compile the code with tasm.
  363.     tasm keygen.asm
  364.     tlink /t keygen.asm
  365.    You must link with the /t option for the keygen to run,
  366.    it makes it a com file.
  367.  
  368. 9. Congratulations! You have just made your first(?) keygen!
  369.  
  370.  
  371. Flywheel V1.02b
  372. (http://www.plannetarium.com)
  373.  
  374. 1. Start the Program
  375.  
  376. 2. Select Register
  377.  
  378. 3. Go into Soft-Ice by pressing Ctrl-D, and set a breakpoint on
  379.    GetDlgItemTextA. Type 'bpx getdlgitemtexta'. Now Press Ctrl-D
  380.    again to get out from Soft-Ice.
  381.  
  382. 4. Enter your name ('TERAPHY') and any serial ('12345').
  383.    Press OK button, and Soft-Ice will show up.
  384.  
  385. Scroll up a little bit and you'll see this
  386.  
  387. :00402ACD 8D4C242C                lea ecx, [esp+2C]
  388. :00402AD1 66AB                    stosw
  389. :00402AD3 6800010000              push 00000100
  390. :00402AD8 51                      push ecx
  391. :00402AD9 6A65                    push 00000065
  392. :00402ADB 56                      push esi
  393. :00402ADC AA                      stosb
  394. :00402ADD FF151C154100            Call [USER32!GetDlgItemTextA]
  395.  
  396. The important adress is there your name is being pushed, and
  397. that is push ecx. ecx got is value from 'lea ecx,[esp+2C]'.
  398. Type 'd esp+2c', and you should see your name.
  399.  
  400. Below is a call to GetDlgItemInt, and as you remember it returns
  401. the inputed value to eax. Type '? eax' to see the serial you wrote.
  402.  
  403. Below this, you'll see this
  404.  
  405. :00402AF3 8D54242C                lea edx, [esp+2C]
  406. :00402AF7 50                      push eax
  407. :00402AF8 52                      push edx
  408. :00402AF9 E8D2F9FFFF              call 004024D0
  409. :00402AFE 83C408                  add esp, 00000008
  410. :00402B01 85C0                    test eax, eax
  411.  
  412. 'lea edx,[esp+2C]' moves the offset of your name into edx,
  413. and then it pushes to stack. And eax contains our serial.
  414. And after the call it tests if eax is true or false.
  415. This call is there the registration code is being calculated.
  416.  
  417. We trace into it. Step past the first instructions until you reach
  418.  
  419. :004024EF B81F85EB51              mov eax, 51EB851F
  420. :004024F4 F7E7                    mul edi
  421. :004024F6 C1EA05                  shr edx, 05
  422. :004024F9 52                      push edx
  423. :004024FA 56                      push esi
  424. :004024FB E8B0000000              call 004025B0
  425.  
  426. 004024EF - 004024F6 makes edx all digits except the two last
  427. of what we typed in as serial. If you wrote '12345' edx will
  428. be '123', and if you wrote '072597' edx will be '0725'.
  429.  
  430. Then it pushes edx and esi. esi is the offset to your name.
  431. Trace into the call. Step past a few instructions until you reach
  432.  
  433. :004025B8 8A06                    mov al, byte ptr [esi]
  434. esi contains the offset to your name, so this instrucion moves
  435. the ascii code of the first letter to al, in my case '54'
  436.  
  437. :004025BA 84C0                    test al, al
  438. :004025BC 7426                    je 004025E4
  439. This instrucions checks if we have inputed any name, if not it jumps.
  440.  
  441. :004025BE 0FBEC0                  movsx eax, al
  442. This instrucion moves al, to eax. If eax = FFFFFF54,
  443. after this eax would have been 00000054
  444.  
  445. :004025C1 50                      push eax
  446. :004025C2 E889140000              call 00403A50
  447. At a first look this call only moves the eax value to ecx.
  448. But it does also check for a space (20h) in eax. It returns
  449. false if not a space.
  450.  
  451. :004025C7 83C404                  add esp, 00000004
  452. This code changes the stack and should be ignored
  453.  
  454. :004025CA 85C0                    test eax, eax
  455. :004025CC 750E                    jne 004025DC
  456. Test if a space was found. Jump if found.
  457.  
  458. :004025CE 0FBE0E                  movsx ecx, byte ptr [esi]
  459. This moves the letter into ecx (there it should already be).
  460.  
  461. :004025D1 51                      push ecx
  462. :004025D2 E8E9120000              call 004038C0
  463. If you, as in my case, wrote your name with a capital letter,
  464. this call will return eax = ascii code for your letter + 20h.
  465. This means it has been converted to a small letter.
  466.  
  467. :004025D7 83C404                  add esp, 00000004
  468. Ignore this
  469.  
  470. :004025DA 03F8                    add edi, eax
  471. Add edi, eax. Eax is the value of our char as small letter.
  472.  
  473. :004025DC 8A4601                  mov al, byte ptr [esi+01]
  474. :004025DF 46                      inc esi
  475. Moves the value of the next char into al
  476.  
  477. :004025E0 84C0                    test al, al
  478. :004025E2 75DA                    jne 004025BE
  479. Test if al is 0. This means the end of our name has been reached.
  480. Jump if al is not 0.
  481.  
  482. What this code has done, as you probably already figured out, is
  483. add the ascii value of all chars into edi. Except spaces (20h).
  484. It has also converted all capital chars into small letters.
  485.  
  486. :004025E4 8B4C2410                mov ecx, [esp+10]
  487. This moves what we typed in (except the last two digits) into ecx
  488.  
  489. :004025E8 8D14BF                  lea edx, [edi+4*edi]
  490. :004025EB 2BCF                    sub ecx, edi
  491. :004025ED 8D1457                  lea edx, [edi+2*edx]
  492. :004025F0 85D2                    test edx, edx
  493. :004025F2 740F                    je 00402603
  494. :004025F4 B8ABAAAAAA              mov eax, AAAAAAAB
  495. :004025F9 F7E2                    mul edx
  496. :004025FB D1EA                    shr edx, 1
  497. :004025FD 81C204060200            add edx, 00020604
  498. :00402603 33C0                    xor eax, eax
  499. :00402605 3BCA                    cmp ecx, edx
  500.  
  501. This code checks if you typed in the right number.
  502. At 402605 the compare is made. But ecx is no longer
  503. what we wrote as serial, because of the 'sub ecx,edi'
  504. command. We could make a simple equation of this.
  505.  
  506. Assume X is our registration code (except the two digits).
  507.     'X - EDI = EDX'
  508.  
  509. Now type '? edx+edi' and, in my case, I'll get '136182'
  510. as decimal value. This is my regcode, except the two last
  511. digits. These digits could be anything.
  512. Now then we know my registration code is '13618200',
  513. we can start on the keygen.
  514.  
  515. 5. Run W32Dasm and dissasemble flywheel.exe (the file is located
  516.     in 'C:\Program Files\Plannet Crafters\Flywheel')
  517.    Save the dissasembly to disk and quit.
  518.  
  519. 6. Now it's time to start on the code. We can use the same start
  520.     as in the last keygen. We go directly to the ripping part.
  521.  
  522. You can start by copy all code from 4025B8 to 402605 into your program.
  523. That will look like this.
  524.  
  525. :004025B8 8A06                    mov al, byte ptr [esi]
  526. :004025BA 84C0                    test al, al
  527. :004025BC 7426                    je 004025E4
  528. :004025BE 0FBEC0                  movsx eax, al
  529. :004025C1 50                      push eax
  530. :004025C2 E889140000              call 00403A50
  531. :004025C7 83C404                  add esp, 00000004
  532. :004025CA 85C0                    test eax, eax
  533. :004025CC 750E                    jne 004025DC
  534. :004025CE 0FBE0E                  movsx ecx, byte ptr [esi]
  535. :004025D1 51                      push ecx
  536. :004025D2 E8E9120000              call 004038C0
  537. :004025D7 83C404                  add esp, 00000004
  538. :004025DA 03F8                    add edi, eax
  539. :004025DC 8A4601                  mov al, byte ptr [esi+01]
  540. :004025DF 46                      inc esi
  541. :004025E0 84C0                    test al, al
  542. :004025E2 75DA                    jne 004025BE
  543. :004025E4 8B4C2410                mov ecx, dword ptr [esp+10]
  544. :004025E8 8D14BF                  lea edx, dword ptr [edi+4*edi]
  545. :004025EB 2BCF                    sub ecx, edi
  546. :004025ED 8D1457                  lea edx, dword ptr [edi+2*edx]
  547. :004025F0 85D2                    test edx, edx
  548. :004025F2 740F                    je 00402603
  549. :004025F4 B8ABAAAAAA              mov eax, AAAAAAAB
  550. :004025F9 F7E2                    mul edx
  551. :004025FB D1EA                    shr edx, 1
  552. :004025FD 81C204060200            add edx, 00020604
  553. :00402603 33C0                    xor eax, eax
  554. :00402605 3BCA                    cmp ecx, edx
  555.  
  556. Here is how I would have ripped this into the program,
  557. with comments.
  558.  
  559. ; THIS REPLACES 4025BE - 4025E2
  560.     
  561.     xor ecx,ecx
  562.     xor edi,edi
  563.     mov di, offset NameSto+2    ; Mov the offset of your name
  564.                     ; into edi
  565. anotherchar:
  566.     movsx eax, byte ptr [di]    ; Get char from [di]
  567.                     
  568.     cmp eax, 20h            ; Compare your letter with 20h
  569.     je space            ; Jump if equal
  570.  
  571.     cmp eax, 041h            ; Compare your letter to see
  572.     jb capital            ; if it's already is a
  573.     cmp eax, 05Ah            ; small lettter
  574.     ja capital
  575.     add eax,20h            ; If capital char, add 20h to make
  576.                     ; it a small letter.
  577. capital:
  578.     add ecx, eax            ; add eax to ecx, if not space
  579. space:
  580.  
  581.     inc di                ; inc di to make it point to the
  582.                     ; next char.
  583.  
  584.     cmp byte ptr [di], 0dh        ; Compare next char with 0Dh (return)
  585.                     ; Remember then we get our name, it
  586.                     ; ends with a 0Dh
  587.  
  588.     jne anotherchar            ; Jump if not 0Dh
  589.     mov edi, ecx
  590.  
  591. ; CODE BELOW REPLACES 4025E2 - 402603
  592. ; All commands with ecx (our inputed code) is not needed
  593. ; because we do not input any code.
  594.  
  595.     xor edx,edx
  596.     lea edx, [edi + 4*edi]
  597.     lea edx, [edi + 2*edx]
  598.     mov eax, 0AAAAAAABh
  599.     mul edx
  600.     shr edx, 1
  601.     add edx, 20604h
  602.  
  603.     xor ecx, ecx        ; Here we do our equation
  604.     add ecx, edx        ; 
  605.     add ecx, edi        ; ecx = edx + edi
  606.  
  607. After this, ecx contains the regcode.
  608. The complete source could look like this.
  609.  
  610. Code Segment Byte Public
  611. Assume   Ds:Code,Cs:Code
  612. Org  100h
  613. P386
  614.  
  615. Start:
  616.  
  617.     mov  ah,09
  618.     mov  dx,offset Intro
  619.     int  21h        ; Show intro msg
  620.  
  621.     mov  ah,0Ah
  622.     mov  dx,offset Namesto
  623.     int  21h        ; Get name
  624.  
  625.     xor ecx,ecx
  626.     xor edi,edi
  627.     mov di, offset NameSto+2
  628. anotherchar:
  629.     movsx eax, byte ptr [di]
  630.     cmp eax, 20h
  631.     je space
  632.     cmp eax, 041h
  633.     jb capital
  634.     cmp eax, 05Ah
  635.     ja capital
  636.     add eax,20h
  637. capital:
  638.     add ecx, eax
  639. space:
  640.     inc di
  641.     cmp byte ptr [di], 0dh
  642.     jne anotherchar
  643.     mov edi, ecx
  644.     xor edx,edx
  645.     lea edx, [edi + 4*edi]
  646.     lea edx, [edi + 2*edx]
  647.     mov eax, 0AAAAAAABh
  648.     mul edx
  649.     shr edx, 1
  650.     add edx, 20604h
  651.     xor ecx, ecx
  652.     add ecx, edx
  653.     add ecx, edi
  654.  
  655.     xor esi,esi
  656.         mov si,offset Serial+9
  657.     mov eax,ecx
  658.         mov ecx,0Ah
  659. KeepGoing:
  660.         xor edx,edx
  661.         div ecx
  662.         add dl,30h
  663.         cmp dl,3Ah
  664.         jl  printnow
  665.         add dl,7
  666. printnow:
  667.         dec esi
  668.         mov [esi],dl
  669.         or eax,eax
  670.         jnz keepgoing
  671.  
  672.     mov ah, 9
  673.     mov dx, offset RegPrompt
  674.     int 21h
  675.     
  676.     int 20h
  677.  
  678. Intro        db 13,10,'FLYWHEEL 1.2 *KEYGEN*'
  679.         db 13,10,'CODED BY TERAPHY [PC97]',13,10
  680.         db 13,10,'Enter your name: $'
  681.  
  682. RegPrompt     db 13,10,'Your registration key is: '
  683. Serial        db 0,0,0,0,0,0,0,0,0,'0','0',13,10,24h
  684.  
  685. Namesto        db 18h,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  686.  
  687. Code Ends
  688. End Start
  689.  
  690.  
  691. Now compile, run and enjoy! :)
  692.  
  693.  
  694. ==================
  695. = TERAPHY [PC97] =
  696. =   07/25/1997   =
  697. ==================